package com.szt.sy.config.security.authentication.provider;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.szt.sy.entity.SessionUser;
import com.szt.sy.service.system.menu.MenuService;
import com.szt.sy.service.system.user.UserService;
import com.szt.sy.util.security.SecurityUtils;
import com.szt.sy.util.spring.HttpContextUtils;
import com.szt.sy.util.web.IpUtils;

/***
 * 管理员安全认证
 * 
 * @author wwy
 *
 */
public class AdminAuthenticationProvider implements AuthenticationProvider {
	
	private final UserDetailsService userDetailsService;
	
	private final PasswordEncoder passwordEncoder;
	
	private MenuService menuService;
	
	public AdminAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
		this.userDetailsService = userDetailsService;
		this.passwordEncoder = passwordEncoder;
	}
	
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
		UserService userService = (UserService) userDetailsService;
		String username = token.getName();
		// 从数据库找到的用户
		SessionUser sessionUser = null;
		if (username != null) {
			sessionUser = (SessionUser) userService.loadUserByUsername(username);
		}
		if (sessionUser == null || sessionUser.getUser() == null) {
			throw new UsernameNotFoundException("用户名或者密码错误");
		} else if (!sessionUser.isEnabled()) {
			throw new DisabledException("用户已被禁用");
		} else if (!sessionUser.isAccountNonExpired()) {
			throw new AccountExpiredException("账号已过期");
		} else if (!sessionUser.isAccountNonLocked()) {
			throw new LockedException("账号已被锁定");
		} else if (!sessionUser.isCredentialsNonExpired()) {
			throw new LockedException("登录凭证已过期");
		}
		// 数据库用户的密码
		String password = sessionUser.getPassword();
		// 与authentication里面的credentials相比较
		// if (!passwordEncoder.matches(token.getCredentials().toString(),
		// password)) {
		// throw new BadCredentialsException("用户名或者密码错误");
		// }
		// 登录成功
		HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
		userService.updateLastLogin(sessionUser.getUser().getId(), IpUtils.getIpAddr(request));
		sessionUser.setLoginInfoHash(SecurityUtils.getLoginInfoHash(request));
		sessionUser.setAuthorities(userService.getAllGrantedAuthority());
		sessionUser.setMenuList(menuService.getAllMenuAuthorityByRole(sessionUser.getUser().getRoleId(),
				sessionUser.getUser().getAllRights()));
		return new UsernamePasswordAuthenticationToken(sessionUser, password, sessionUser.getAuthorities());
	}
	
	@Override
	public boolean supports(Class<?> authentication) {
		// 返回true后才会执行上面的authenticate方法,这步能确保authentication能正确转换类型
		return UsernamePasswordAuthenticationToken.class.equals(authentication);
	}
	
	public void setMenuService(MenuService menuService) {
		this.menuService = menuService;
	}
}